From f6d93de51e0cb8bb97b4a56761ad1b926838585e Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Thu, 4 Aug 2005 09:00:16 +0000 Subject: [PATCH] The attached patch removes all of the console handling code from Xend and changes xm to simply exec /usr/libexec/xen/xc_console. I've done a pretty good amount of testing and this seems to clear up all of the Xend console issues in bugzilla. This is a pretty big change to Xend though with a lot of deleted code so I'd appreciate if people more familiar with the Xend codebase could look through it critically. In addition to the patch, the following files are no longer used: tools/python/xen/util/console_client.py tools/python/xen/xend/XendConsole.py tools/python/xen/xend/server/SrvConsole.py tools/python/xen/xend/server/SrvConsoleDir.py tools/python/xen/xend/server/console.py Regards, Anthony Liguori Signed-off-by: Anthony Liguori --- tools/Makefile | 2 +- tools/misc/xend | 2 + tools/python/xen/util/console_client.py | 108 ----- tools/python/xen/xend/XendClient.py | 17 +- tools/python/xen/xend/XendConsole.py | 44 -- tools/python/xen/xend/XendDomainInfo.py | 41 +- tools/python/xen/xend/XendRoot.py | 19 - tools/python/xen/xend/server/SrvConsole.py | 41 -- tools/python/xen/xend/server/SrvConsoleDir.py | 59 --- tools/python/xen/xend/server/SrvDomain.py | 10 - tools/python/xen/xend/server/SrvRoot.py | 1 - tools/python/xen/xend/server/SrvServer.py | 2 +- tools/python/xen/xend/server/console.py | 391 ------------------ tools/python/xen/xend/server/event.py | 8 - tools/python/xen/xend/server/messages.py | 10 - tools/python/xen/xm/create.py | 29 +- tools/python/xen/xm/main.py | 45 +- 17 files changed, 21 insertions(+), 808 deletions(-) delete mode 100644 tools/python/xen/util/console_client.py delete mode 100644 tools/python/xen/xend/XendConsole.py delete mode 100644 tools/python/xen/xend/server/SrvConsole.py delete mode 100644 tools/python/xen/xend/server/SrvConsoleDir.py delete mode 100755 tools/python/xen/xend/server/console.py diff --git a/tools/Makefile b/tools/Makefile index 2c668a59b9..629294e776 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -13,7 +13,7 @@ SUBDIRS += xcutils #SUBDIRS += pygrub SUBDIRS += firmware SUBDIRS += security -#SUBDIRS += consoled +SUBDIRS += consoled .PHONY: all install clean check check_clean ioemu eioemuinstall ioemuclean diff --git a/tools/misc/xend b/tools/misc/xend index 06f5e660ec..706c838428 100644 --- a/tools/misc/xend +++ b/tools/misc/xend @@ -130,6 +130,8 @@ def main(): return status >> 8 elif sys.argv[1] == 'start': start_xcs() + if os.fork() == 0: + os.execvp('/usr/sbin/consoled', ['/usr/sbin/consoled']); return daemon.start() elif sys.argv[1] == 'trace_start': start_xcs() diff --git a/tools/python/xen/util/console_client.py b/tools/python/xen/util/console_client.py deleted file mode 100644 index c0acacfad3..0000000000 --- a/tools/python/xen/util/console_client.py +++ /dev/null @@ -1,108 +0,0 @@ -#!/usr/bin/env python - -############################################## -# Console client for Xen guest OSes -# Copyright (c) 2004, K A Fraser -############################################## - -import errno, os, signal, socket, struct, sys - -from termios import * -# Indexes into termios.tcgetattr() list. -IFLAG = 0 -OFLAG = 1 -CFLAG = 2 -LFLAG = 3 -ISPEED = 4 -OSPEED = 5 -CC = 6 - -def __child_death(signum, frame): - global stop - stop = True - -def __recv_from_sock(sock): - global stop - stop = False - while not stop: - try: - data = sock.recv(1024) - except socket.error, error: - if error[0] != errno.EINTR: - raise - else: - try: - os.write(1, data) - except os.error, error: - if error[0] != errno.EINTR: - raise - os.wait() - -def __send_to_sock(sock): - while 1: - try: - data = os.read(0,1024) - except os.error, error: - if error[0] != errno.EINTR: - raise - else: - if ord(data[0]) == ord(']')-64: - break - try: - sock.send(data) - except socket.error, error: - if error[0] == errno.EPIPE: - sys.exit(0) - if error[0] != errno.EINTR: - raise - sys.exit(0) - -def connect(host, port, path=None): - # Try inet first. If 'path' is given and the error - # was connection refused, try unix-domain on 'path'. - try: - sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - sock.connect((host, port)) - except socket.error, err: - if (path is None) or (err[0] != errno.ECONNREFUSED): - raise - # Try unix-domain. - sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) - sock.connect(path) - - oattrs = tcgetattr(0) - nattrs = tcgetattr(0) - nattrs[IFLAG] = nattrs[IFLAG] & ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON) - nattrs[OFLAG] = nattrs[OFLAG] & ~(OPOST) - nattrs[CFLAG] = nattrs[CFLAG] & ~(CSIZE | PARENB) - nattrs[CFLAG] = nattrs[CFLAG] | CS8 - nattrs[LFLAG] = nattrs[LFLAG] & ~(ECHO | ICANON | IEXTEN | ISIG) - nattrs[CC][VMIN] = 1 - nattrs[CC][VTIME] = 0 - - if os.fork(): - signal.signal(signal.SIGCHLD, __child_death) - print "************ REMOTE CONSOLE: CTRL-] TO QUIT ********" - tcsetattr(0, TCSAFLUSH, nattrs) - try: - __recv_from_sock(sock) - finally: - tcsetattr(0, TCSAFLUSH, oattrs) - print - print "************ REMOTE CONSOLE EXITED *****************" - else: - signal.signal(signal.SIGPIPE, signal.SIG_IGN) - __send_to_sock(sock) - -if __name__ == '__main__': - argc = len(sys.argv) - if argc < 3 or argc > 4: - print >>sys.stderr, sys.argv[0], " []" - sys.exit(1) - host = sys.argv[1] - port = int(sys.argv[2]) - if argc > 3: - path = sys.argv[3] - else: - path = None - connect(host, port, path=path) diff --git a/tools/python/xen/xend/XendClient.py b/tools/python/xen/xend/XendClient.py index 24812f4abb..868836c30f 100644 --- a/tools/python/xen/xend/XendClient.py +++ b/tools/python/xen/xend/XendClient.py @@ -5,9 +5,7 @@ Callable as a script - see main(). Supports inet or unix connection to xend. This API is the 'control-plane' for xend. -The 'data-plane' is done separately. For example, consoles -are accessed via sockets on xend, but the list of consoles -is accessible via this API. +The 'data-plane' is done separately. """ import os import sys @@ -146,9 +144,6 @@ class Xend: def domainurl(self, id=''): return self.url.relative('domain/' + str(id)) - def consoleurl(self, id=''): - return self.url.relative('console/' + str(id)) - def deviceurl(self, id=''): return self.url.relative('device/' + str(id)) @@ -318,16 +313,6 @@ class Xend: 'idx' : idx, 'config' : fileof(config) }) - def xend_consoles(self): - return self.xendGet(self.consoleurl()) - - def xend_console(self, id): - return self.xendGet(self.consoleurl(id)) - - def xend_console_disconnect(self, id): - return self.xendPost(self.consoleurl(id), - {'op' : 'disconnect'}) - def xend_vnets(self): return self.xendGet(self.vneturl()) diff --git a/tools/python/xen/xend/XendConsole.py b/tools/python/xen/xend/XendConsole.py deleted file mode 100644 index 7a04f5ddde..0000000000 --- a/tools/python/xen/xend/XendConsole.py +++ /dev/null @@ -1,44 +0,0 @@ -# Copyright (C) 2004 Mike Wray - -import XendRoot; xroot = XendRoot.instance() -from XendError import XendError - -class XendConsole: - - def __init__(self): - pass - - def console_ls(self): - return [ c.console_port for c in self.consoles() ] - - def consoles(self): - l = [] - xd = XendRoot.get_component('xen.xend.XendDomain') - for vm in xd.list(): - ctrl = vm.getDeviceController("console", error=False) - if (not ctrl): continue - console = ctrl.getDevice(0) - if (not console): continue - l.append(console) - return l - - def console_get(self, id): - id = int(id) - for c in self.consoles(): - if c.console_port == id: - return c - return None - - def console_disconnect(self, id): - console = self.console_get(id) - if not console: - raise XendError('Invalid console id') - console.disconnect() - -def instance(): - global inst - try: - inst - except: - inst = XendConsole() - return inst diff --git a/tools/python/xen/xend/XendDomainInfo.py b/tools/python/xen/xend/XendDomainInfo.py index f846bb72de..3e016b681f 100644 --- a/tools/python/xen/xend/XendDomainInfo.py +++ b/tools/python/xen/xend/XendDomainInfo.py @@ -268,7 +268,6 @@ class XendDomainInfo: self.restart_time = None self.restart_count = 0 - self.console_port = None self.vcpus = 1 self.bootloader = None @@ -344,9 +343,6 @@ class XendDomainInfo: s += " name=" + self.name s += " memory=" + str(self.memory) s += " ssidref=" + str(self.ssidref) - console = self.getConsole() - if console: - s += " console=" + str(console.console_port) s += ">" return s @@ -443,9 +439,6 @@ class XendDomainInfo: sxpr.append(self.store_channel.sxpr()) if self.store_mfn: sxpr.append(['store_mfn', self.store_mfn]) - console = self.getConsole() - if console: - sxpr.append(console.sxpr()) if self.restart_count: sxpr.append(['restart_count', self.restart_count]) @@ -519,7 +512,6 @@ class XendDomainInfo: # Create domain devices. self.configure_backends() - self.configure_console() self.configure_restart() self.construct_image() self.configure() @@ -785,17 +777,6 @@ class XendDomainInfo: """ self.bootloader = sxp.child_value(self.config, "bootloader") - def configure_console(self): - """Configure the vm console port. - """ - x = sxp.child_value(self.config, 'console') - if x: - try: - port = int(x) - except: - raise VmError('invalid console:' + str(x)) - self.console_port = port - def configure_restart(self): """Configure the vm restart mode. """ @@ -855,7 +836,7 @@ class XendDomainInfo: def restart(self): """Restart the domain after it has exited. - Reuses the domain id and console port. + Reuses the domain id """ try: @@ -910,25 +891,9 @@ class XendDomainInfo: """ self.configure_fields() - self.create_console() self.create_devices() self.create_blkif() - def create_console(self): - console = self.getConsole() - if not console: - config = ['console'] - if self.console_port: - config.append(['console_port', self.console_port]) - console = self.createDevice('console', config) - return console - - def getConsole(self): - console_ctrl = self.getDeviceController("console", error=False) - if console_ctrl: - return console_ctrl.getDevice(0) - return None - def create_blkif(self): """Create the block device interface (blkif) for the vm. The vm needs a blkif even if it doesn't have any disks @@ -1048,7 +1013,6 @@ add_config_handler('memory', vm_field_ignore) add_config_handler('ssidref', vm_field_ignore) add_config_handler('cpu', vm_field_ignore) add_config_handler('cpu_weight', vm_field_ignore) -add_config_handler('console', vm_field_ignore) add_config_handler('restart', vm_field_ignore) add_config_handler('image', vm_field_ignore) add_config_handler('device', vm_field_ignore) @@ -1062,9 +1026,6 @@ add_config_handler('maxmem', vm_field_maxmem) #============================================================================ # Register device controllers and their device config types. -from server import console -controller.addDevControllerClass("console", console.ConsoleController) - from server import blkif controller.addDevControllerClass("vbd", blkif.BlkifController) add_device_handler("vbd", "vbd") diff --git a/tools/python/xen/xend/XendRoot.py b/tools/python/xen/xend/XendRoot.py index 3d3767f9ba..57d5fe6848 100644 --- a/tools/python/xen/xend/XendRoot.py +++ b/tools/python/xen/xend/XendRoot.py @@ -70,12 +70,6 @@ class XendRoot: """Default path the unix-domain server listens at.""" xend_unix_path_default = '/var/lib/xend/xend-socket' - """Default interface address xend listens at for consoles.""" - console_address_default = 'localhost' - - """Default port xend serves consoles at. """ - console_port_base_default = '9600' - dom0_min_mem_default = '0' dom0_cpus_default = '0' @@ -302,19 +296,6 @@ class XendRoot: """ return self.get_config_value("xend-unix-path", self.xend_unix_path_default) - def get_console_address(self): - """Get the address xend listens at for its console ports. - This defaults to 'localhost', allowing only the localhost to connect - to the console ports. Setting this to the empty string, allows all - hosts to connect. - """ - return self.get_config_value('console-address', self.console_address_default) - - def get_console_port_base(self): - """Get the base port number used to generate console ports for domains. - """ - return self.get_config_int('console-port-base', self.console_port_base_default) - def get_block_script(self, type): return self.get_config_value('block-%s' % type, '') diff --git a/tools/python/xen/xend/server/SrvConsole.py b/tools/python/xen/xend/server/SrvConsole.py deleted file mode 100644 index f147f2810b..0000000000 --- a/tools/python/xen/xend/server/SrvConsole.py +++ /dev/null @@ -1,41 +0,0 @@ -# Copyright (C) 2004 Mike Wray - -from xen.xend import sxp -from xen.xend import XendConsole -from xen.web.SrvDir import SrvDir - -class SrvConsole(SrvDir): - """An individual console. - """ - - def __init__(self, info): - SrvDir.__init__(self) - self.info = info - self.xc = XendConsole.instance() - - def op_disconnect(self, op, req): - val = self.xc.console_disconnect(self.info.console_port) - return val - - def render_POST(self, req): - return self.perform(req) - - def render_GET(self, req): - if self.use_sxp(req): - req.setHeader("Content-Type", sxp.mime_type) - sxp.show(self.info.sxpr(), out=req) - else: - req.write('') - self.print_path(req) - #self.ls() - req.write('

%s

' % self.info) - req.write('

Connect to domain %d

' - % (self.info.uri(), self.info.id)) - self.form(req) - req.write('') - - def form(self, req): - req.write('
' % req.prePathURL()) - if self.info.connected(): - req.write('') - req.write('
') diff --git a/tools/python/xen/xend/server/SrvConsoleDir.py b/tools/python/xen/xend/server/SrvConsoleDir.py deleted file mode 100644 index 5c15eebb0f..0000000000 --- a/tools/python/xen/xend/server/SrvConsoleDir.py +++ /dev/null @@ -1,59 +0,0 @@ -# Copyright (C) 2004 Mike Wray - -from xen.web.SrvDir import SrvDir -from SrvConsole import SrvConsole -from xen.xend import XendConsole -from xen.xend import sxp - -class SrvConsoleDir(SrvDir): - """Console directory. - """ - - def __init__(self): - SrvDir.__init__(self) - self.xconsole = XendConsole.instance() - - def console(self, x): - val = None - try: - info = self.xconsole.console_get(x) - val = SrvConsole(info) - except KeyError, ex: - print 'SrvConsoleDir>', ex - pass - return val - - def get(self, x): - v = SrvDir.get(self, x) - if v is not None: - return v - v = self.console(x) - return v - - def render_GET(self, req): - if self.use_sxp(req): - req.setHeader("Content-Type", sxp.mime_type) - self.ls_console(req, 1) - else: - req.write("") - self.print_path(req) - self.ls(req) - self.ls_console(req) - #self.form(req.wfile) - req.write("") - - def ls_console(self, req, use_sxp=0): - url = req.prePathURL() - if not url.endswith('/'): - url += '/' - if use_sxp: - consoles = self.xconsole.console_ls() - sxp.show(consoles, out=req) - else: - consoles = self.xconsole.consoles() - consoles.sort(lambda x, y: cmp(x.console_port, y.console_port)) - req.write('
    ') - for c in consoles: - cid = str(c.console_port) - req.write('
  • %s
  • ' % (url, cid, cid)) - req.write('
') diff --git a/tools/python/xen/xend/server/SrvDomain.py b/tools/python/xen/xend/server/SrvDomain.py index fc8fd4420b..6e51e69518 100644 --- a/tools/python/xen/xend/server/SrvDomain.py +++ b/tools/python/xen/xend/server/SrvDomain.py @@ -4,7 +4,6 @@ from xen.web import http from xen.xend import sxp from xen.xend import XendDomain -from xen.xend import XendConsole from xen.xend import PrettyPrint from xen.xend.Args import FormFn @@ -18,7 +17,6 @@ class SrvDomain(SrvDir): SrvDir.__init__(self) self.dom = dom self.xd = XendDomain.instance() - self.xconsole = XendConsole.instance() def op_configure(self, op, req): """Configure an existing domain. @@ -208,14 +206,6 @@ class SrvDomain(SrvDir): self.print_path(req) #self.ls() req.write('

%s

' % self.dom) - if self.dom.console: - cinfo = self.dom.console - cid = str(cinfo.console_port) - #todo: Local xref: need to know server prefix. - req.write('

Console %s

' - % (cid, cid)) - req.write('

Connect to console

' - % cinfo.uri()) if self.dom.config: req.write("
")
                 PrettyPrint.prettyprint(self.dom.config, out=req)
diff --git a/tools/python/xen/xend/server/SrvRoot.py b/tools/python/xen/xend/server/SrvRoot.py
index 84ef008118..3c92f5d692 100644
--- a/tools/python/xen/xend/server/SrvRoot.py
+++ b/tools/python/xen/xend/server/SrvRoot.py
@@ -15,7 +15,6 @@ class SrvRoot(SrvDir):
     subdirs = [
         ('node',    'SrvNode'       ),
         ('domain',  'SrvDomainDir'  ),
-        ('console', 'SrvConsoleDir' ),
         ('vnet',    'SrvVnetDir'    ),
         ]
 
diff --git a/tools/python/xen/xend/server/SrvServer.py b/tools/python/xen/xend/server/SrvServer.py
index 1816c1c56d..2c87e104de 100644
--- a/tools/python/xen/xend/server/SrvServer.py
+++ b/tools/python/xen/xend/server/SrvServer.py
@@ -1,7 +1,7 @@
 #!/usr/bin/python
 # Copyright (C) 2004 Mike Wray 
 
-"""Example xend HTTP and console server.
+"""Example xend HTTP
 
    Can be accessed from a browser or from a program.
    Do 'python SrvServer.py' to run the server.
diff --git a/tools/python/xen/xend/server/console.py b/tools/python/xen/xend/server/console.py
deleted file mode 100755
index e0aa04a37a..0000000000
--- a/tools/python/xen/xend/server/console.py
+++ /dev/null
@@ -1,391 +0,0 @@
-# Copyright (C) 2004 Mike Wray 
-
-import socket
-import threading
-from errno import EAGAIN, EINTR, EWOULDBLOCK
-    
-from xen.web import reactor, protocol
-
-from xen.lowlevel import xu
-
-from xen.xend.XendError import XendError
-from xen.xend import EventServer; eserver = EventServer.instance()
-from xen.xend.XendLogging import log
-from xen.xend import XendRoot; xroot = XendRoot.instance()
-from xen.xend import sxp
-from xen.xend.xenstore import DBVar
-
-from xen.xend.server.controller import CtrlMsgRcvr, Dev, DevController
-from xen.xend.server.messages import *
-from xen.xend.server.params import *
-
-class ConsoleProtocol(protocol.Protocol):
-    """Asynchronous handler for a console socket.
-    """
-
-    def __init__(self, console, id):
-        self.console = console
-        self.id = id
-        self.addr = None
-
-    def connectionMade(self, addr=None):
-        peer = self.transport.getPeer()
-        self.addr = addr
-        if self.console.connect(self.addr, self):
-            self.transport.write("Cannot connect to console %d on domain %d\n"
-                                 % (self.id, self.console.getDomain()))
-            self.loseConnection()
-            return
-        else:
-            if len(self.addr) == 2:
-                host = str(self.addr[0])
-                port = str(self.addr[1])
-            else:
-                host = 'localhost'
-                port = str(addr)
-            log.info("Console connected %s %s %s",
-                     self.id, host, port)
-            eserver.inject('xend.console.connect',
-                           [self.id, host, port])
-
-    def dataReceived(self, data):
-        if self.console.receiveInput(self, data):
-            self.loseConnection()
-
-    def write(self, data):
-        self.transport.write(data)
-        return len(data)
-
-    def connectionLost(self, reason=None):
-        log.info("Console disconnected %s %s %s",
-                 str(self.id), str(self.addr[0]), str(self.addr[1]))
-        eserver.inject('xend.console.disconnect',
-                       [self.id, self.addr[0], self.addr[1]])
-        self.console.disconnect(conn=self)
-
-    def loseConnection(self):
-        self.transport.loseConnection()
-
-class ConsoleDev(Dev, protocol.ServerFactory):
-    """Console device for a domain.
-    Does not poll for i/o itself, but relies on the domain to post console
-    output and the connected TCP sockets to post console input.
-    """
-
-    STATUS_NEW       = 'new'
-    STATUS_CLOSED    = 'closed'
-    STATUS_CONNECTED = 'connected'
-    STATUS_LISTENING = 'listening'
-
-    __exports__ = Dev.__exports__ + [
-        DBVar('status',       ty='str'),
-        #DBVar('listening',    ty='str'),
-        DBVar('console_port', ty='int'),
-        ]
-
-    def __init__(self, controller, id, config, recreate=False):
-        Dev.__init__(self, controller, id, config)
-        self.lock = threading.RLock()
-        self.status = self.STATUS_NEW
-        self.addr = None
-        self.conn = None
-        self.console_port = None
-        self.obuf = xu.buffer()
-        self.ibuf = xu.buffer()
-        self.channel = None
-        self.listening = False
-        self.unix_listener = None
-        self.tcp_listener = None
-        
-        console_port = sxp.child_value(self.config, "console_port")
-        if console_port is None:
-            console_port = xroot.get_console_port_base() + self.getDomain()
-        self.checkConsolePort(console_port)
-        self.console_port = console_port
-        
-        log.info("Created console id=%d domain=%d port=%d",
-                 self.id, self.getDomain(), self.console_port)
-        eserver.inject('xend.console.create',
-                       [self.id, self.getDomain(), self.console_port])
-
-    def init(self, recreate=False, reboot=False):
-        try:
-            self.lock.acquire()
-            self.destroyed = False
-            self.channel = self.getChannel()
-            self.listen()
-        finally:
-            self.lock.release()
-
-    def checkConsolePort(self, console_port):
-        """Check that a console port is not in use by another console.
-        """
-        xd = XendRoot.get_component('xen.xend.XendDomain')
-        for vm in xd.list():
-            ctrl = vm.getDeviceController(self.getType(), error=False)
-            if (not ctrl): continue
-            ctrl.checkConsolePort(console_port)
-    
-    def sxpr(self):
-        try:
-            self.lock.acquire()
-            val = ['console',
-                   ['status', self.status ],
-                   ['id',     self.id    ],
-                   ['domain', self.getDomain() ] ]
-            val.append(['local_port',   self.getLocalPort()  ])
-            val.append(['remote_port',  self.getRemotePort() ])
-            val.append(['console_port', self.console_port    ])
-            if self.addr:
-                val.append(['connected', self.addr[0], self.addr[1]])
-        finally:
-            self.lock.release()
-        return val
-
-    def getLocalPort(self):
-        try:
-            self.lock.acquire()
-            if self.channel:
-                return self.channel.getLocalPort()
-            else:
-                return 0
-        finally:
-            self.lock.release()
-
-    def getRemotePort(self):
-        try:
-            self.lock.acquire()
-            if self.channel:
-                return self.channel.getRemotePort()
-            else:
-                return 0
-        finally:
-            self.lock.release()
-
-    def uri(self):
-        """Get the uri to use to connect to the console.
-        This will be a telnet: uri.
-
-        return uri
-        """
-        host = socket.gethostname()
-        return "telnet://%s:%d" % (host, self.console_port)
-
-    def closed(self):
-        return self.status == self.STATUS_CLOSED
-
-    def connected(self):
-        return self.status == self.STATUS_CONNECTED
-
-    def destroy(self, change=False, reboot=False):
-        """Close the console.
-        """
-        if reboot:
-            return
-        try:
-            self.lock.acquire()
-            self.status = self.STATUS_CLOSED
-            self.listening = False
-            if self.conn:
-                self.conn.loseConnection()
-            if self.tcp_listener:
-                self.tcp_listener.stopListening()
-                self.tcp_listener = None
-            if self.unix_listener:
-                self.unix_listener.stopListening()
-                self.unix_listener = None
-        finally:
-            self.lock.release()
-
-    def listen(self):
-        """Listen for TCP connections to the console port..
-        """
-        try:
-            self.lock.acquire()
-            if self.closed():
-                return
-            if self.listening:
-                pass
-            else:
-                self.listening = True
-                self.status = self.STATUS_LISTENING
-                if xroot.get_xend_unix_server():
-                    path = '/var/lib/xend/console-%s' % self.console_port
-                    self.unix_listener = reactor.listenUNIX(path, self)
-                if xroot.get_xend_http_server():
-                    interface = xroot.get_console_address()
-                    self.tcp_listener = reactor.listenTCP(
-                        self.console_port, self, interface=interface)
-        finally:
-            self.lock.release()
-
-    def buildProtocol(self, addr):
-        """Factory function called to create the protocol when a connection is accepted
-        by listenTCP.
-        """
-        proto = ConsoleProtocol(self, self.id)
-        proto.factory = self
-        return proto
-
-    def connect(self, addr, conn):
-        """Connect a TCP connection to the console.
-        Fails if closed or already connected.
-
-        addr peer address
-        conn connection
-
-        returns 0 if ok, negative otherwise
-        """
-        try:
-            self.lock.acquire()
-            if self.closed():
-                return -1
-            if self.connected():
-                return -1
-            self.addr = addr
-            self.conn = conn
-            self.status = self.STATUS_CONNECTED
-            self.writeOutput()
-        finally:
-            self.lock.release()
-        return 0
-
-    def disconnect(self, conn=None):
-        """Disconnect the TCP connection to the console.
-        """
-        try:
-            self.lock.acquire()
-            if conn and conn != self.conn: return
-            if self.conn:
-                self.conn.loseConnection()
-            self.addr = None
-            self.conn = None
-            self.status = self.STATUS_LISTENING
-            self.listen()
-        finally:
-            self.lock.release()
-
-    def receiveOutput(self, msg):
-        """Receive output console data from the console channel.
-
-        msg     console message
-        type    major message type
-        subtype minor message typ
-        """
-        # Treat the obuf as a ring buffer.
-        try:
-            self.lock.acquire()
-            data = msg.get_payload()
-            data_n = len(data)
-            if self.obuf.space() < data_n:
-                self.obuf.discard(data_n)
-            if self.obuf.space() < data_n:
-                data = data[-self.obuf.space():]
-            self.obuf.write(data)
-            self.writeOutput()
-        finally:
-            self.lock.release()
-        
-    def writeOutput(self):
-        """Handle buffered output from the console device.
-        Sends it to the connected TCP connection (if any).
-        """
-        try:
-            self.lock.acquire()
-            if self.closed():
-                return -1
-            writes = 0
-            while self.conn and (writes < 100) and (not self.obuf.empty()):
-                try:
-                    writes += 1
-                    bytes = self.conn.write(self.obuf.peek())
-                    if bytes > 0:
-                        self.obuf.discard(bytes)
-                except socket.error, err:
-                    if err.args[0] in (EWOULDBLOCK, EAGAIN, EINTR):
-                        pass
-                    else:
-                        self.disconnect()
-                        break
-                        
-        finally:
-            self.lock.release()
-        return 0
-    
-    def receiveInput(self, conn, data):
-        """Receive console input from a TCP connection.  Ignores the
-        input if the calling connection (conn) is not the one
-        connected to the console (self.conn).
-
-        conn connection
-        data input data
-        """
-        try:
-            self.lock.acquire()
-            if self.closed(): return -1
-            if conn != self.conn: return 0
-            self.ibuf.write(data)
-            self.writeInput()
-        finally:
-            self.lock.release()
-        return 0
-
-    def writeInput(self):
-        """Write pending console input to the console channel.
-        Writes as much to the channel as it can.
-        """
-        try:
-            self.lock.acquire()
-            while self.channel and not self.ibuf.empty():
-                msg = xu.message(CMSG_CONSOLE, 0, 0)
-                msg.append_payload(self.ibuf.read(msg.MAX_PAYLOAD))
-                self.channel.writeRequest(msg)
-        finally:
-            self.lock.release()
-
-class ConsoleController(DevController):
-    """Device controller for all the consoles for a domain.
-    """
-
-    def __init__(self, vm, recreate=False):
-        DevController.__init__(self, vm, recreate=recreate)
-        self.rcvr = None
-
-    def initController(self, recreate=False, reboot=False):
-        self.destroyed = False
-        self.rcvr = CtrlMsgRcvr(self.getChannel())
-        self.rcvr.addHandler(CMSG_CONSOLE,
-                             0,
-                             self.receiveOutput)
-        self.rcvr.registerChannel()
-        if reboot:
-            self.rebootDevices()
-
-    def destroyController(self, reboot=False):
-        self.destroyed = True
-        self.destroyDevices(reboot=reboot)
-        self.rcvr.deregisterChannel()
-
-    def newDevice(self, id, config, recreate=False):
-        return ConsoleDev(self, id, config, recreate=recreate)
-
-    def checkConsolePort(self, console_port):
-        """Check that a console port is not in use by a console.
-        """
-        for c in self.getDevices():
-            if c.console_port == console_port:
-                raise XendError('console port in use: ' + str(console_port))
-
-    def receiveOutput(self, msg):
-        """Handle a control request.
-        The CMSG_CONSOLE messages just contain data, and no console id,
-        so just send to console 0 (if there is one).
-
-        todo: extend CMSG_CONSOLE to support more than one console?
-        """
-        console = self.getDevice(0)
-        if console:
-            console.receiveOutput(msg)
-        else:
-            log.warning('no console: domain %d', self.getDomain())
-
diff --git a/tools/python/xen/xend/server/event.py b/tools/python/xen/xend/server/event.py
index f16c786c3e..0346fee43e 100644
--- a/tools/python/xen/xend/server/event.py
+++ b/tools/python/xen/xend/server/event.py
@@ -128,16 +128,8 @@ class EventProtocol(protocol.Protocol):
     def op_pretty(self, name, req):
         self.pretty = 1
 
-    def op_console_disconnect(self, name, req):
-        id = sxp.child_value(req, 'id')
-        if not id:
-            raise XendError('Missing console id')
-        id = int(id)
-        self.daemon.console_disconnect(id)
-
     def op_info(self, name, req):
         val = ['info']
-        #val += self.daemon.consoles()
         #val += self.daemon.blkifs()
         #val += self.daemon.netifs()
         #val += self.daemon.usbifs()
diff --git a/tools/python/xen/xend/server/messages.py b/tools/python/xen/xend/server/messages.py
index 84fc738e68..9c9e405a7a 100644
--- a/tools/python/xen/xend/server/messages.py
+++ b/tools/python/xen/xend/server/messages.py
@@ -17,16 +17,6 @@ See below.
 """
 msg_formats = {}
 
-#============================================================================
-# Console message types.
-#============================================================================
-
-CMSG_CONSOLE  = 0
-
-console_formats = { 'console_data': (CMSG_CONSOLE, 0) }
-
-msg_formats.update(console_formats)
-
 #============================================================================
 # Block interface message types.
 #============================================================================
diff --git a/tools/python/xen/xm/create.py b/tools/python/xen/xm/create.py
index 6b4d8a27ed..cfae6d0b87 100644
--- a/tools/python/xen/xm/create.py
+++ b/tools/python/xen/xm/create.py
@@ -7,6 +7,7 @@ import random
 import string
 import sys
 import socket
+import commands
 
 import xen.lowlevel.xc
 
@@ -17,8 +18,6 @@ from xen.xend.XendBootloader import bootloader
 from xen.xend import XendRoot; xroot = XendRoot.instance()
 from xen.util import blkif
 
-from xen.util import console_client
-
 from xen.xm.opts import *
 
 gopts = Opts(use="""[options] [vars]
@@ -145,10 +144,6 @@ gopts.var('cpu_weight', val='WEIGHT',
           use="""Set the new domain's cpu weight.
           WEIGHT is a float that controls the domain's share of the cpu.""")
 
-gopts.var('console', val='PORT',
-          fn=set_int, default=None,
-          use="Console port to use. Default is 9600 + domain id.")
-
 gopts.var('restart', val='onreboot|always|never',
           fn=set_value, default=None,
           use="""Whether the domain should be restarted on exit.
@@ -471,8 +466,6 @@ def make_config(opts, vals):
         config.append(['backend', ['netif']])
     if vals.restart:
         config.append(['restart', vals.restart])
-    if vals.console:
-        config.append(['console', vals.console])
 
     if vals.bootloader:
         run_bootloader(opts, config, vals)
@@ -620,8 +613,8 @@ def make_domain(opts, config):
 
     @param opts:   options
     @param config: configuration
-    @return: domain id, console port
-    @rtype:  (int, int)
+    @return: domain id
+    @rtype:  int
     """
 
     try:
@@ -634,19 +627,13 @@ def make_domain(opts, config):
         opts.err(str(ex))
 
     dom = sxp.child_value(dominfo, 'name')
-    console_info = sxp.child(dominfo, 'console')
-    if console_info:
-        console_port = int(sxp.child_value(console_info, 'console_port'))
-    else:
-        console_port = None
 
     if not opts.vals.paused:
         if server.xend_domain_unpause(dom) < 0:
             server.xend_domain_destroy(dom)
             opts.err("Failed to unpause domain %s" % dom)
-    opts.info("Started domain %s, console on port %d"
-              % (dom, console_port))
-    return (dom, console_port)
+    opts.info("Started domain %s" % (dom))
+    return int(sxp.child_value(dominfo, 'id'))
 
 def get_dom0_alloc():
     """Return current allocation memory of dom0 (in MB). Return 0 on error"""
@@ -709,10 +696,10 @@ def main(argv):
         if dom0_min_mem != 0:
             balloon_out(dom0_min_mem, opts)
 
-        (dom, console) = make_domain(opts, config)
+        dom = make_domain(opts, config)
         if opts.vals.console_autoconnect:
-            path = "/var/lib/xend/console-%s" % console
-            console_client.connect('localhost', console, path=path)
+            cmd = "/usr/libexec/xen/xc_console %d" % dom
+            os.execvp('/usr/libexec/xen/xc_console', cmd.split())
         
 if __name__ == '__main__':
     main(sys.argv)
diff --git a/tools/python/xen/xm/main.py b/tools/python/xen/xm/main.py
index 141da198ca..d890380103 100644
--- a/tools/python/xen/xm/main.py
+++ b/tools/python/xen/xm/main.py
@@ -4,6 +4,7 @@
 import os
 import os.path
 import sys
+import commands
 from getopt import getopt
 import socket
 import warnings
@@ -390,7 +391,7 @@ class ProgList(Prog):
             self.brief_list(doms)
 
     def brief_list(self, doms):
-        print 'Name              Id  Mem(MB)  CPU VCPU(s)  State  Time(s)  Console'
+        print 'Name              Id  Mem(MB)  CPU VCPU(s)  State  Time(s)'
         for dom in doms:
             info = server.xend_domain(dom)
             d = {}
@@ -401,19 +402,14 @@ class ProgList(Prog):
             d['vcpus'] = int(sxp.child_value(info, 'vcpus', '0'))
             d['state'] = sxp.child_value(info, 'state', '??')
             d['cpu_time'] = float(sxp.child_value(info, 'cpu_time', '0'))
-            console = sxp.child(info, 'console')
-            if console:
-                d['port'] = sxp.child_value(console, 'console_port')
-            else:
-                d['port'] = ''
             if d['vcpus'] > 1:
                 d['cpu'] = '-'
             if ((int(sxp.child_value(info, 'ssidref', '0'))) != 0):
                 d['ssidref1'] =  int(sxp.child_value(info, 'ssidref', '0')) & 0xffff
                 d['ssidref2'] = (int(sxp.child_value(info, 'ssidref', '0')) >> 16) & 0xffff
-                print ("%(name)-16s %(dom)3d  %(mem)7d  %(cpu)3s  %(vcpus)5d   %(state)5s  %(cpu_time)7.1f     %(port)4s    s:%(ssidref2)02x/p:%(ssidref1)02x" % d)
+                print ("%(name)-16s %(dom)3d  %(mem)7d  %(cpu)3s  %(vcpus)5d   %(state)5s  %(cpu_time)7.1f     %s:%(ssidref2)02x/p:%(ssidref1)02x" % d)
             else:
-                print ("%(name)-16s %(dom)3d  %(mem)7d  %(cpu)3s  %(vcpus)5d   %(state)5s  %(cpu_time)7.1f     %(port)4s" % d)
+                print ("%(name)-16s %(dom)3d  %(mem)7d  %(cpu)3s  %(vcpus)5d   %(state)5s  %(cpu_time)7.1f" % d)
 
     def show_vcpus(self, doms):
         print 'Name              Id  VCPU  CPU  CPUMAP'
@@ -699,29 +695,6 @@ class ProgInfo(Prog):
 
 xm.prog(ProgInfo)
 
-class ProgConsoles(Prog):
-    group = 'console'
-    name = "consoles"
-    info = """Get information about domain consoles."""
-
-    def main(self, args):
-        l = server.xend_consoles()
-        print "Dom Port  Id Connection"
-        for x in l:
-            info = server.xend_console(x)
-            d = {}
-            d['dom'] = sxp.child(info, 'domain', '?')[1]
-            d['port'] = sxp.child_value(info, 'console_port', '?')
-            d['id'] = sxp.child_value(info, 'id', '?')
-            connected = sxp.child(info, 'connected')
-            if connected:
-                d['conn'] = '%s:%s' % (connected[1], connected[2])
-            else:
-                d['conn'] = ''
-            print "%(dom)3s %(port)4s %(id)3s %(conn)s" % d
-
-xm.prog(ProgConsoles)
-
 class ProgConsole(Prog):
     group = 'console'
     name = "console"
@@ -735,13 +708,9 @@ class ProgConsole(Prog):
         if len(args) < 2: self.err("%s: Missing domain" % args[0])
         dom = args[1]
         info = server.xend_domain(dom)
-        console = sxp.child(info, "console")
-        if not console:
-            self.err("No console information")
-        port = sxp.child_value(console, "console_port")
-        from xen.util import console_client
-        path = "/var/lib/xend/console-%s" % port
-        console_client.connect("localhost", int(port), path=path)
+        domid = int(sxp.child_value(info, 'id', '-1'))
+        cmd = "/usr/libexec/xen/xc_console %d" % domid
+        os.execvp('/usr/libexec/xen/xc_console', cmd.split())
 
 xm.prog(ProgConsole)
 
-- 
2.30.2